<?php
// +----------------------------------------------------------------------+
// | Author:  Evgeny Leontev <eleontev@gmail.com>                         |
// | Copyright (c) 2005 Evgeny Leontev                                    |
// +----------------------------------------------------------------------+
// | This source file is free software; you can redistribute it and/or    |
// | modify it under the terms of the GNU Lesser General Public           |
// | License as published by the Free Software Foundation; either         |
// | version 2.1 of the License, or (at your option) any later version.   |
// |                                                                      |
// | This source file is distributed in the hope that it will be useful,  |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    |
// | Lesser General Public License for more details.                      |
// +----------------------------------------------------------------------+

class CommonTreeModel extends AppModel
{
	
	
	function getRecordsSql() { 
		$sql = "
		SELECT 
			c.*,
			c.id AS category_id,
			COUNT(ec.entry_id) AS num_entries 
		FROM 
			{$this->tbl->category} c
		LEFT JOIN {$this->tbl->entry_to_category} ec ON c.id = ec.category_id
		WHERE {$this->sql_params}
		GROUP BY c.id
		{$this->sql_params_order}";

		return $sql;
	}
	
	
	function &getRecords() {
		$data = array();
		$sql = $this->getRecordsSql();
		$result =& $this->db->Execute($sql) or die(db_error($sql));
		while($row = $result->FetchRow()){
			$data[$row['id']] = $row;
		}

		return $data;
	}

	
	// get helper array in format id=>level
	function &getTreeHelperArray($arr, $parent_id = 0) {
		
		if(!$arr) { return array(); }
		
		$tree = &new TreeHelper();
		foreach($arr as $k => $row) {
			$tree->setTreeItem($row['id'], $row['parent_id']);
		}
		
		return $tree->getTreeHelper($parent_id);
	}
	
	
	// FOR FORM SELECT // ---------------------
	
	// just for select
	function &getSelectRecords($sort = false) { 
	
		$sort = ($sort) ? $sort : 'sort_order';
	
		$sql = "SELECT id as id1, id, parent_id, name, sort_order 
		FROM {$this->tbl->category} c
		ORDER BY {$sort}";
		$result =& $this->db->Execute($sql) or die(db_error($sql));
		return $result->GetAssoc();
	}
	
	
	// to generate form select range $arr from getSelectRecords
	function &getSelectRange($arr, $parent_id = 0, $pref = '-- ') {
		
		if(!$arr) { return array(); }
		
		$tree_helper = &$this->getTreeHelperArray($arr, $parent_id);
		foreach($tree_helper as $id => $level) {
	
			$p = ($level == 0) ? '' : str_repeat($pref, $level);
			$data[$id] = $p . $arr[$id]['name'];
		}
		
		return $data;
	}
	
	// generate arrays for js (DynamicOptionList) $arr from getSelectRecords
	function &getSortJsArray($arr) {
		
		$values = array();
		foreach($arr as $v) {
			$str =  "'%s: %s', '%s'";
			$values[$v['parent_id']][] = sprintf($str, 'AFTER', addslashes($v['name']), $v['sort_order']);
		}
		
		
		$sort = new TableSortOrder(); $str = '';
		unset($sort->extra_range['sort_default']);
		foreach($sort->extra_range as $k => $v) {
			$str .= sprintf("'%s', '%s', ", $v, $k);
		}
		
		foreach($values as $k => $v) {
			$values[$k] = "'" . $k . "'," . $str . implode(',', $v);
		}
		
		return $values;
	}
	
	
	// PRIVATE RELATED //-----------------
	
	function getMemberRoleSelectRange() {
		$r = new RoleModel();
		return $r->getSelectRange('member');
	}	
	
	
	function isPrivate($id) {
		$sql = "SELECT private FROM {$this->tbl->category} WHERE id = '{$id}'";
		$result =& $this->db->Execute($sql) or die(db_error($sql));
		return $result->Fields('private');		
	}
	
	
	// ACTIONS // ---------------------
	
	//  return sort val and dod nessesary updates in sort_order field
	function sortManipulation(&$obj) {
		
		$parent_id = $obj->get('parent_id');
		
		$sort = new TableSortOrder();
		$sort->table = $this->tbl->category;
		$sort->name_field = 'name';
		$sort->sort_field = 'sort_order';
		$sort->setMoreSql("parent_id = '{$parent_id}'",
		                  "parent_id = '{$parent_id}'");
		
		$val = $sort->getDoSort($obj->get('sort_order'), $obj->get('id'));
		$obj->set('sort_order', $val);
	}
	
	
	// DELETE RELATED // ---------------------
		
	// return how much entries for current if some product assigned to category 
	function isCategoryInUse($record_id) {
		$sql = "SELECT COUNT(*) AS num FROM {$this->tbl->entry_to_category} 
		WHERE category_id = ?";
		$result =& $this->db->Execute($sql, $record_id) or die(db_error($sql));
		return $result->Fields('num');
	}
	
	
	// change sort_order for all categories with the same parent
	function setCategoryOrder($record_id, $parent_id) {
		
		$sql = "SELECT sort_order FROM {$this->tbl->category} WHERE id = '$record_id'";
		$result = &$this->db->Execute($sql) or die(db_error($sql));
		$order = $result->Fields('sort_order');
		
		$sql = "UPDATE {$this->tbl->category} 
		SET sort_order = (sort_order-1)
		WHERE parent_id = '$parent_id'
		AND sort_order > $order";
		
		return $this->db->Execute($sql) or die(db_error($sql));
	}		
	
	// delete category
	function deleteCategory($record_id) {
		$sql = "DELETE FROM {$this->tbl->category} WHERE id IN (?)";
		return $this->db->Execute($sql, $record_id) or die(db_error($sql));
	}
	
	
	// change parent when delete a category
	function setCategoryToParent($record_id, $parent_id) {
		$sql = "UPDATE {$this->tbl->category} 
		SET parent_id = '$parent_id'
		WHERE parent_id = '$record_id'";
		return $this->db->Execute($sql) or die(db_error($sql));
	}
	
	
	// change product to parent category when delete a category
	function setCategoryEntryToParent($record_id, $parent_id) {
		$sql = "UPDATE {$this->tbl->entry_to_category} 
		SET category_id = '$parent_id'
		WHERE category_id = '$record_id'";
		return $this->db->Execute($sql) or die(db_error($sql));
	}
	
	
	function save(&$obj, $action) {
		
		$this->sortManipulation($obj);
		
		if($action == 'insert') {
			$id = $this->add($obj);
			
			if($this->isExtra('private')) {
				$this->saveMemberRoleToCategory($obj, $id);
			}
			
			if($this->isExtra('notify_admin_category')) {
				$this->saveAdminUserToCategory($obj, $id);
			}
			
			
		} else {
			$id = $obj->get('id');
			$this->update($obj, $id);
			
			if($this->isExtra('private')) {
				$this->deleteMemberRoleToCategory($id);
				if($obj->get('private')) {
					$this->saveMemberRoleToCategory($obj, $id);
				}
			}
			
			if($this->isExtra('notify_admin_category')) {
				$this->deleteAdminUserToCategory($id);
				$this->saveAdminUserToCategory($obj, $id);
			}
		}
		
		return true;
	}	
	
	
	
	// DELETE RELATED // ---------------------
		
	function delete($id, $parent_id) {
		
		$ret = 'notdeleteable_category';
		$in_use = $this->isCategoryInUse($id);
		
		// top level category is in use, notdeleteable
		if($parent_id == 0 && $in_use) {
			$ret = 'notdeleteable_category';
		
		// top level category but not in use
		} elseif($parent_id == 0 && !$in_use) {
			
			//DBUtil::begin();
			$this->setCategoryOrder($id, $parent_id);			
			$this->deleteCategory($id);
			$this->setCategoryToParent($id, $parent_id);
			
			if($this->isExtra('private')) {
				$this->deleteMemberRoleToCategory($id);
			}
			
			//DBUtil::commit(); 
			
			$ret = 'success';
			
		// child category, all values assigned to parent
		} else {
			
			//DBUtil::begin();
			$this->setCategoryOrder($id, $parent_id);
			$this->deleteCategory($id);
			$this->setCategoryToParent($id, $parent_id);
			$this->setCategoryEntryToParent($id, $parent_id);
			
			if($this->isExtra('private')) {
				$this->deleteMemberRoleToCategory($id);
			}
			
			//DBUtil::commit();
			
			$ret = 'success';
		}
		
		return $ret;
	}	
}
?>